package edu.pku.sei.mte.utilities;

import java.io.File;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import agg.attribute.impl.ValueMember;
import agg.attribute.impl.ValueTuple;
import agg.xt_basis.Arc;
import agg.xt_basis.GraGra;
import agg.xt_basis.Graph;
import agg.xt_basis.GraphObject;
import agg.xt_basis.Node;
import agg.xt_basis.Type;
import agg.xt_basis.TypeException;
import edu.pku.sei.mte.compositetrans.TResult;
import edu.pku.sei.mte.mtemodel.metamodel.RAttribute;
import edu.pku.sei.mte.mtemodel.metamodel.RTypeGraph;
import edu.pku.sei.mte.mtemodel.model.MAttribute;
import edu.pku.sei.mte.mtemodel.model.MClass;
import edu.pku.sei.mte.mtemodel.model.MModelGraph;
import edu.pku.sei.mte.mtemodel.model.MReference;
import edu.pku.sei.mte.runtime.Environment;
import edu.pku.sei.mte.serialization.EcoreLoader;
import edu.pku.sei.mte.serialization.EcoreXMISaver;

public class Utility {

	public static ResourceSet resourceSet = new ResourceSetImpl();
	public static Environment cur_env = null;
	
	public static TResult getCorrectModelFormat(TResult obj, ModelFormat targetFormat){
		if(obj.modelFormat.equals(targetFormat))
			return obj;
		else if(obj.modelFormat.equals(ModelFormat.EMF) && targetFormat.equals(ModelFormat.PKUMT)){
			
		}else if(obj.modelFormat.equals(ModelFormat.PKUMT) && targetFormat.equals(ModelFormat.EMF)){
			
		}
		return null;
	}
	
	public static void PKUMT2EMF(MModelGraph model, EcoreLoader ecoreLoader, Resource resource) {
		new EcoreXMISaver().PKUMT2EMF(model, ecoreLoader, resource);
	}
	
	public static void PKUMT2GGX(TResult obj, GraGra graphGrammar) throws TypeException{
		Enumeration<Type> types = graphGrammar.getTypes();
		Map<String, Type> typeMap = new HashMap<String, Type>();
		while(types.hasMoreElements()){
			Type type = types.nextElement();
			typeMap.put(type.getName(), type);
		}
		MModelGraph model = (MModelGraph) obj.targetModel;
		Graph graph = graphGrammar.getGraph();
		Map<MClass, Node> nodeMap = new HashMap<MClass, Node>();
		for(MClass mc : model.getNodes()){
			Node node = graph.createNode(typeMap.get(mc.getType().getName()));
			for(RAttribute ra : mc.getType().getAttributes()){
				ValueMember vm = (ValueMember) ((ValueTuple) node.getAttribute()).getMemberAt(ra.getName());
				MAttribute ma = mc.getAttribute(ra.getName());
				if(ma != null && ma.getValue()!= null)
					vm.setExprAsObject((String)ma.getValue());
				else vm.setExprAsObject("");
			}
			nodeMap.put(mc, node);
		}
		for(MReference mr : model.getEdges()){
			String arcName = mr.getType().getTargetRole();
			graph.createArc(typeMap.get(arcName), nodeMap.get(mr.getSource()), nodeMap.get(mr.getTarget()));
		}
		graphGrammar.save("UMLADtoBPEL\\temp\\agg.in");
	}
	
	public static MModelGraph GGX2PKUMT(GraGra graphGrammar, RTypeGraph typeGraph) throws TypeException{
		MModelGraph model = new MModelGraph();
		model.setTypeGraph(typeGraph);
		Graph graph = graphGrammar.getGraph();
		Map<GraphObject, MClass> nodeMap = new HashMap<GraphObject, MClass>();
		Enumeration<Node> nodes = graph.getNodes();
		int count = 0;
		while(nodes.hasMoreElements()){
			Node n = nodes.nextElement();
			MClass mc = new MClass();
			mc.setType(typeGraph.getTypeClass(n.getType().getName()));
			for(RAttribute ra : mc.getType().getAttributes()){
				if(ra.getName().equals("id")){
					mc.getAttribute(ra.getName()).setValue(Integer.toString(count++));
					continue;
				}
				ValueMember vm = (ValueMember) ((ValueTuple) n.getAttribute()).getMemberAt(ra.getName());
				MAttribute ma = mc.getAttribute(ra.getName());
				ma.setValue(vm.getExprAsObject());
			}
//			mc.getAttribute("id").setValue(Integer.toString(count++));
			model.addNode(mc);
			nodeMap.put(n, mc);
		}
		Enumeration<Arc> arcs = graph.getArcs();
		while(arcs.hasMoreElements()){
			Arc a = arcs.nextElement();
			MReference mr = new MReference();
			mr.setType(typeGraph.getTypeReference("", null, "", null, a.getType().getName()));
			mr.setSource(nodeMap.get(a.getSource()));
			mr.setTarget(nodeMap.get(a.getTarget()));
			model.addEdge(mr);
		}
		return model;
	}

	public static Element loadXML(String filename){
		DocumentBuilderFactory factory = null;
		factory = DocumentBuilderFactory.newInstance();
		factory.setIgnoringComments(true);
		factory.setIgnoringElementContentWhitespace(true);
		factory.setNamespaceAware(true);
		File file = new File(filename);
		if(!file.exists()){
			System.out.println("file not exist!");
			return null;
		}
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(file);
			return doc.getDocumentElement();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}
